package com.zyht.wechat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wx.core.process.JEEWeiXinX509TrustManager;
import com.wx.core.process.WxApi;
import com.zyht.redis.service.RedisService;

public class RedisLockAccessTokenVisitorImpl implements AccessTokenVisitor{

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Resource
	private RedisService redisService;
	
	@Resource
	private RedisAccessTokenVistor redisAccessTokenVistor;
	
	@Override
	public String getTokenSequence(String wxid,String appId,String appSecret){

		String accessToken = redisAccessTokenVistor.getTokenSequence(wxid);
		//使用分布式锁
		if(null == accessToken){
			int i = 0;
			while(!redisService.setNX("com.zyht.wechat.AccessToken.lock", "1").booleanValue()){
				try {
					TimeUnit.MILLISECONDS.sleep(200);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				i++;
				if(i==15){
					break;
				}
			}
			redisService.expire("com.zyht.wechat.AccessToken.lock", 5l);
			accessToken = redisAccessTokenVistor.getTokenSequence(wxid);
			if(null == accessToken){
				String tokenUrl = WxApi.getTokenUrl(appId,appSecret);
				AccessToken token = getAccessTokenByHttp(tokenUrl);
				if(null!=token){
					this.redisAccessTokenVistor.persist(wxid, token);
					accessToken = token.getAccessToken();
				}else{
					logger.error("获取AccessToken异常，相关信息是：\n tokenUrl->"+ tokenUrl);
				}
			}
			redisService.del("com.zyht.wechat.AccessToken.lock");
		}
		return accessToken;
	}

	private final AccessToken getAccessTokenByHttp(String urlString){
		TrustManager[] tm = { new JEEWeiXinX509TrustManager() };
		StringBuffer buffer = new StringBuffer();
		try{
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new  URL(urlString);
			HttpsURLConnection conn =(HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(5000);
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
		} catch (KeyManagementException | NoSuchAlgorithmException | NoSuchProviderException
			| IOException e){
			e.printStackTrace();
			logger.error(e.getLocalizedMessage());
			return null;
		}
		JSONObject jsonObj = JSONObject.parseObject(buffer.toString());
		logger.debug("获取AccessToken响应是："+ buffer.toString());
		return JSON.toJavaObject(jsonObj,AccessToken.class);
	}
}
